//
//  InsuredDevice.m
//  PhotoAnnotate
//
//  Created by Bassem El-Tamimi on 07.03.11.
//  Copyright 2011 ePapyrus GmbH. All rights reserved.
//

#import "InsuredDevice.h"

#import <SystemConfiguration/SystemConfiguration.h>
#import <dlfcn.h>
#import <mach/port.h>
#import <mach/kern_return.h>
#import <mach/mach.h>
#import <mach/mach_host.h>

#include <sys/types.h>
#include <sys/sysctl.h>


@implementation InsuredDevice

@synthesize localizedMachineNames;
@synthesize insuredDevicePricelist;


- (id) init {
	
    self = [super init];
    if (self) {
		
		NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
		NSArray* languages = [defs objectForKey:@"AppleLanguages"];
		NSString* preferredLang = [languages objectAtIndex:0];
		
		if ([preferredLang compare:@"de"] == NSOrderedSame) {
			localizedMachineNames = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"MachineNames_de" ofType:@"plist"]];

		} else {
			localizedMachineNames = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"MachineNames_en" ofType:@"plist"]];
		}
    }
	
	self.insuredDevicePricelist = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"InsuredDevicePricelist" ofType:@"plist"]];
	
    return self;
}


- (NSString *)machine
{
	size_t size;
	
	// Set 'oldp' parameter to NULL to get the size of the data
	// returned so we can allocate appropriate amount of space
	sysctlbyname("hw.machine", NULL, &size, NULL, 0); 
	
	// Allocate the space to store name
	char *name = malloc(size);
	
	// Get the platform name
	sysctlbyname("hw.machine", name, &size, NULL, 0);
	
	// Place name into a string
	
	NSString *machine = [NSString stringWithCString:name encoding:NSASCIIStringEncoding];
	//NSString *machine = [NSString stringWithCString:name];
	
	
	// Done with this
	free(name);
	
	return machine;
}


- (NSString *)machineMemory
{
	float bytes = 0.0f;  
    NSError *error = nil;  
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  
    NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error: &error];  
    
    if (dictionary) {  
        NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize];  
        bytes = [fileSystemSizeInBytes floatValue];  
    } else {  
        NSLog(@"Error Obtaining File System Info: Domain = %@, Code = %@", [error domain], [error code]);  
    }
	
	float gigaSize = bytes / (1024 * 1024 * 1024);
		
	NSString *memoryString = nil;
	
	if (gigaSize < 8.0) {
		memoryString = @"8";
	} else if (gigaSize < 16.0) {
		memoryString = @"16";
	} else if (gigaSize < 32.0) {
		memoryString = @"32";
	} else if (gigaSize < 64.0) {
		memoryString = @"64";
	} else {
		memoryString = @"> 64";
	}
		
	return memoryString;
}


- (NSString *)deviceDescription
{
	if ([localizedMachineNames objectForKey:self.machine] != nil) {
		return [NSString stringWithFormat:@"%@ %@ GB", [localizedMachineNames objectForKey:self.machine], self.machineMemory];
	}
	
	return [NSString stringWithFormat:@"%@ %@ GB", self.machine, self.machineMemory];

}

- (NSString *)devicePrice
{
	NSString *deviceIdentifier = [NSString stringWithFormat:@"%@,%@", [self machine], [self machineMemory]];

	if ([insuredDevicePricelist objectForKey:deviceIdentifier] != nil) {
		return [(NSNumber *)[insuredDevicePricelist objectForKey:deviceIdentifier] stringValue];
	}
	
	return @"0";
}


- (NSString *)serialNumber
{
	NSString *aSerialNumber = nil;
	
	void *IOKit = dlopen("/System/Library/Frameworks/IOKit.framework/IOKit", RTLD_NOW);
	if (IOKit)
	{
		mach_port_t *kIOMasterPortDefault = dlsym(IOKit, "kIOMasterPortDefault");
		CFMutableDictionaryRef (*IOServiceMatching)(const char *name) = dlsym(IOKit, "IOServiceMatching");
		mach_port_t (*IOServiceGetMatchingService)(mach_port_t masterPort, CFDictionaryRef matching) = dlsym(IOKit, "IOServiceGetMatchingService");
		CFTypeRef (*IORegistryEntryCreateCFProperty)(mach_port_t entry, CFStringRef key, CFAllocatorRef allocator, uint32_t options) = dlsym(IOKit, "IORegistryEntryCreateCFProperty");
		kern_return_t (*IOObjectRelease)(mach_port_t object) = dlsym(IOKit, "IOObjectRelease");
		
		if (kIOMasterPortDefault && IOServiceGetMatchingService && IORegistryEntryCreateCFProperty && IOObjectRelease)
		{
			mach_port_t platformExpertDevice = IOServiceGetMatchingService(*kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
			if (platformExpertDevice)
			{
				CFTypeRef platformSerialNumber = IORegistryEntryCreateCFProperty(platformExpertDevice, CFSTR("IOPlatformSerialNumber"), kCFAllocatorDefault, 0);
				if (CFGetTypeID(platformSerialNumber) == CFStringGetTypeID())
				{
					aSerialNumber = [NSString stringWithString:(NSString*)platformSerialNumber];
					CFRelease(platformSerialNumber);
				}
				IOObjectRelease(platformExpertDevice);
			}
		}
		dlclose(IOKit);
		
	}
	
	return aSerialNumber;
}

@end
